<?php

namespace qmq\tp6\command;

use think\console\Command;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Input;
use think\console\Output;
use think\facade\Console;
use think\facade\Db;
use think\helper\Str;
use think\helper\Arr;

class Model extends Command
{

    private $fields = [];
    /**     
     *
     * @var Input
     */
    protected $input;

    protected function configure()
    {
        // 指令配置
        $this->setName('qmq:model')
            ->addArgument('table', Argument::REQUIRED, '表名')
            ->addUsage('生成模型 获取数据库字段与备注')
            ->addOption("namespace", "NS", Option::VALUE_OPTIONAL, '命名空间', 'app\admin\model')
            ->addOption("name", "N", Option::VALUE_OPTIONAL, '模型名称')
            ->addOption("soft", "SF", Option::VALUE_OPTIONAL, "软删除")
            ->addOption("extend", "E", Option::VALUE_OPTIONAL, "继承名称", '\think\Model')
            ->addOption("relations", "R", Option::VALUE_OPTIONAL, "Relation")
            ->addOption("isrelation", null, Option::VALUE_OPTIONAL, 0) //是否是生成关联模型，如果已存在模型，不会重新生成模型文件
            ->setDescription('创建模型');
    }
    protected function execute(Input $input, Output $output)
    {
        $this->input = $input;
        $table = $input->getArgument("table");
        $this->getFields($table)->createModel();
        $output->writeln("模型已生成");
    }


    /**
     * 获取表的字段信息
     *
     * @param string $table 表名
     * @return $this
     */
    private function getFields($table)
    {
        $this->fields =  Db::getFields($table);
        return $this;
    }

    /**
     * 创建模型
     *
     * @return $this
     */
    private function createModel()
    {
        $path = __DIR__ . "/../tpl/Model.php";
        $tpl = file_get_contents($path);

        //命名空间
        $namespace = $this->input->getOption("namespace");


        //模型字段
        $property = [];
        foreach ($this->fields as $field) {
            $property[] = sprintf(" * @property %s \$%s %s", $this->getFieldType($field['type']), $field['name'], $field['comment']);
        }

        //模型名称
        $name = trim($this->input->getOption("name"));
        if (!$name) {
            $table = $this->input->getArgument("table");
            $name = Str::studly($table);
        }

        //继承名称
        $extend = trim($this->input->getOption("extend"));

        //软删除
        if (!$this->input->getOption("soft")) {
            //不存在软删除
            $tpl = str_replace(["use think\model\concern\SoftDelete;", "use SoftDelete;"], ["", ""], $tpl);
        }


        //关联关系
        $relations = json_decode($this->input->getOption("relations"), true);
        if ($relations) {
            $relationsRow = [];
            foreach ($relations as $relation) {
                if (!Arr::has($relation, 'table')) {
                    continue;
                }
                //生成关联模型
                $relationsRow[] = sprintf(
                    '
    public function %s(){
        return $this->%s("%s","%s","%s");
    }
    ',
                    $relation['relation_name'],
                    $relation['type'],
                    Str::studly($relation['table']),
                    $relation['foreign'],
                    $relation['mainkey']
                );
            }
            $tpl = str_replace("//relations", \implode("\r\n", $relationsRow), $tpl);
        }



        $tpl = \str_replace(['app\admin\model', '[property]', 'ModelName', '\think\Model'], [$namespace, implode("\r\n", $property), $name, $extend], $tpl);
        //生成模型保存的目录
        $path = rtrim(base_path(), '/')  . str_replace("\\", '/', trim($namespace, "app"));
        if (!is_dir($path)) {
            mkdir($path, 0775, true);
        }
        $modelFileName = sprintf("%s/%s.php", $path, $name);

        if (is_file($modelFileName)) {
            if ($this->input->getOption("isrelation")) {
                return;
            }
            rename($modelFileName, sprintf("%s/%s_%s.php", $path, $name, date("YmdHis")));
        }
        file_put_contents($modelFileName, $tpl);

        if ($relations) {
            foreach ($relations as $relation) {
                if (!$relation['table']) {
                    continue;
                }
                Console::call("qmq:model", [
                    $relation['table'],
                    "--namespace=" . $namespace,
                    "--extend=" . $extend,
                    "--soft=" . ($relation['soft'] ? 1 : 0),
                    "--isrelation=1"
                ]);
            }
        }
    }

    /**
     * 将mysql的类型转换成php的类型
     *
     * @param string $str mysql的字段类型
     * @return void
     */
    private function getFieldType($str)
    {
        if (Str::startsWith($str, ["int", 'smallint', 'bigint', "year", 'tinyint', 'numeric'])) {
            return "int";
        } else if (Str::startsWith($str, 'float')) {
            return "float";
        } else if (Str::startsWith($str, ['decimal', 'double'])) {
            return 'double';
        }
        //time varchar enum set text date datetime char
        return "string";
    }
}
